home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
glass
/
glass.lha
/
GLASS
/
tmc
/
cll.ct
< prev
next >
Wrap
Text File
|
1990-11-06
|
20KB
|
958 lines
/*
Copyright (C) 1990 C van Reewijk, email: dutentb.uucp!reeuwijk
This file is part of GLASS.
GLASS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GLASS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GLASS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
.. file: cll.ct
..
.. The following variables must be set in tm:
.. basename: the name of the module. used to generate stat_..
.. wantdefs: the names of wanted definitions.
..
.error Warning: 'cll' library is obsolete, use 'cllu' library.
.error 'cll' does not support reading of NIL pointers.
/* ---- start of ${tplfilename} ---- */
/* routines for $(basename).
template file: ${tplfilename}
datastructure file: ${dsfilename}
tm version: $(tmvers) ($(tmdate))
The following C pre-processor variables may be defined:
.if ${index stat_$(basename) $(need_misc)}
STAT If you want code for statistics.
Statistics are written to 'FILE *statstream'.
.endif
FATAL(msg) If you want supply a fatal error handler to print 'msg'.
A default is provided.
Possible declaration or #define'ing of statstream
must be done outside this module.
*/
/* used UNIX functions */
extern char *malloc();
extern char *realloc();
#ifndef WORDBUFSIZE
#define WORDBUFSIZE 100
#endif
.if ${index stat_$(basename) $(need_misc)}
#ifdef STAT
static char tm_allocfreed[] = "%-15s: %6ld allocated, %6ld freed.%s\n";
#endif
.endif
static char *tm_srcfile = __FILE__;
.if ${len $(need_print) $(need_print_list) $(need_fprint) $(need_fprint_list)}
static char tm_niltxt[] = "@";
.endif
#ifndef FATAL
#define FATAL(msg) tmfatal(tm_srcfile,__LINE__,msg)
#endif
/* the possible error messages */
static char tm_outofmemory[] = "out of memory";
.if ${len $(need_fscan_list)}
static char tm_badeof[] = "unexpected end of file";
.endif
.if ${len $(need_fscan)}
static char tm_badcons[] = "bad constructor for %s: '%s'";
.endif
#ifndef FATALTAG
#define FATALTAG(tg) tmbadtag(tm_srcfile,__LINE__,tg)
#endif
.if ${index stat_$(basename) $(need_misc)}
#ifdef STAT
.foreach t $(need_stat)
.if ${len ${telmlist $t}}
static long int newcnt_$t = 0, frecnt_$t = 0;
.else
.foreach c ${conslist $t}
static long int newcnt_$c = 0, frecnt_$c = 0;
.endforeach
.endif
.endforeach
#endif
.endif
/************************************************
* new_<cons> routines *
************************************************/
.foreach t $(need_new)
.if ${index $t $(want_new)}
.set stat
.else
.set stat "static "
.endif
.if ${len ${telmlist $t}}
/* Allocate a new instance of tuple type '$t' */
$(stat)$t new_$t( ${seplist ", " ${prefix "par_" ${telmlist $t}}} )
.foreach sname ${telmlist $t}
.if ${eq list ${ttypeclass $t $(sname)}}
${ttypename $t $(sname)}_list par_$(sname);
.else
${ttypename $t $(sname)} par_$(sname);
.endif
.endforeach
{
$t new;
new = ($t) malloc( sizeof(*new));
if( (char *)new == (char *)0 ){
FATAL( tm_outofmemory );
}
new->next = $tNIL;
.foreach sname ${telmlist $t}
new->$(sname) = par_$(sname);
.endforeach
.if ${index stat_$(basename) $(need_misc)}
#ifdef STAT
newcnt_$t++;
#endif
.endif
return new;
}
.else
.foreach c ${conslist $t}
/* Allocate a new instance of constructor '$c' */
$(stat)$t new_$c( ${seplist ", " ${prefix "par_" ${celmlist $t $c}}} )
.foreach sname ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $(sname)}}
${ctypename $t $c $(sname)}_list par_$(sname);
.else
${ctypename $t $c $(sname)} par_$(sname);
.endif
.endforeach
{
register $c new;
new = ($c) malloc( sizeof(*new));
if( (char *)new == (char *)0 ){
FATAL( tm_outofmemory );
}
new->next = $tNIL;
new->tag = TAG$c;
.foreach sname ${celmlist $t $c}
new->$(sname) = par_$(sname);
.endforeach
.if ${index stat_$(basename) $(need_misc)}
#ifdef STAT
newcnt_$c++;
#endif
.endif
return ($t) new;
}
.endforeach
.endif
.endforeach
/**********************************************************
* fre_<type> and fre_<type>_list routines *
**********************************************************/
.foreach t $(need_fre)
.if ${index $t $(want_fre)}
.set stat
.else
.set stat "static "
.endif
/* free an element of type $t */
$(stat)void fre_$t( e )
$t e;
{
if( e == $tNIL ) return;
free( (char *) e );
.if ${len ${telmlist $t}}
.if ${index stat_$(basename) $(need_misc)}
#ifdef STAT
frecnt_$t++;
#endif
.endif
.else
.if ${index stat_$(basename) $(need_misc)}
#ifdef STAT
switch( e->tag ){
.foreach c ${conslist $t}
case TAG$c:
frecnt_$c++;
break;
.endforeach
default:
FATALTAG( e->tag );
}
#endif
.endif
.endif
}
.endforeach
.foreach t $(need_fre_list)
.if ${index $t $(want_fre_list)}
.set stat
.else
.set stat "static "
.endif
/* free a list of $t elements */
$(stat)void fre_$t_list( e )
register $t_list e;
{
register $t_list n;
while( e!=$tNIL ){
n = e->next;
fre_$t( e );
e = n;
}
}
.endforeach
/**********************************************************
* rfre_<type> and rfre_<type>_list routines *
**********************************************************/
.. forward declarations
.foreach t $(need_rfre)
.if ${index $t $(want_rfre)}
.else
static void rfre_$t();
.endif
.endforeach
.foreach t $(need_rfre_list)
.if ${index $t $(want_rfre_list)}
.else
static void rfre_$t_list();
.endif
.endforeach
.foreach t $(need_rfre)
.if ${index $t $(want_rfre)}
.set stat
.else
.set stat "static "
.endif
/* Recursively free an element of type '$t'
and all elements in it.
*/
$(stat)void rfre_$t( e )
$t e;
{
.if ${len ${telmlist $t}}
if( e == $tNIL ) return;
.foreach sname ${telmlist $t}
.if ${eq list ${ttypeclass $t $(sname)}}
rfre_${ttypename $t $(sname)}_list( e->$(sname) );
.else
rfre_${ttypename $t $(sname)}( e->$(sname) );
.endif
.endforeach
.else
if( e == $tNIL ) return;
switch( e->tag ){
.foreach c ${conslist $t}
case TAG$c:
.foreach sname ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $(sname)}}
rfre_${ctypename $t $c $(sname)}_list( (($c) e)->$(sname) );
.else
rfre_${ctypename $t $c $(sname)}( (($c) e)->$(sname) );
.endif
.endforeach
break;
.endforeach
default:
FATALTAG( e->tag );
}
.endif
fre_$t( e );
}
.endforeach
.foreach t $(need_rfre_list)
.if ${index $t $(want_rfre_list)}
.set stat
.else
.set stat "static "
.endif
/* recursively free a list of elements of type $t */
$(stat)void rfre_$t_list( e )
register $t_list e;
{
register $t n;
while( e!=$tNIL ){
n = e->next;
rfre_$t( e );
e = n;
}
}
.endforeach
/**********************************************************
* app_<type>_list routines *
**********************************************************/
.foreach t $(need_app_list)
.if ${index $t $(want_app_list)}
.set stat
.else
.set stat "static "
.endif
/* append list of $t 'b' after list of $t 'a' */
$(stat)$t app_$t_list( a, b )
$t_list a;
$t b;
{
register $t tl;
if( a == $tNIL ) return b;
tl = a;
while( tl->next != $tNIL ) tl = tl->next;
tl->next = b;
return a;
}
.endforeach
/******************************************************
* print_<type> and print_<type>_list routines *
******************************************************/
.. Forward declarations
.foreach t $(need_print)
.if ${index $t $(want_print)}
.else
static void print_$t();
.endif
.endforeach
.foreach t $(need_print_list)
.if ${index $t $(want_print_list)}
.else
static void print_$t_list();
.endif
.endforeach
.foreach t $(need_print)
.if ${index $t $(want_print)}
.set stat
.else
.set stat "static "
.endif
/* Print an element of type '$t'
* using print optimization routines.
*/
$(stat)void print_$t( t )
$t t;
{
if( t==$tNIL ){
printword( tm_niltxt );
return;
}
.if ${len ${telmlist $t}}
opentuple();
.foreach sname ${telmlist $t}
.if ${eq list ${ttypeclass $t $(sname)}}
print_${ttypename $t $(sname)}_list( t->$(sname) );
.else
print_${ttypename $t $(sname)}( t->$(sname) );
.endif
.endforeach
closetuple();
.else
opencons();
switch( t->tag ){
.foreach c ${conslist $t}
case TAG$c:
printword( "$c" );
.foreach sname ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $(sname)}}
print_${ctypename $t $c $(sname)}_list( (($c) t)->$(sname) );
.else
print_${ctypename $t $c $(sname)}( (($c) t)->$(sname) );
.endif
.endforeach
break;
.endforeach
default:
FATALTAG( t->tag );
}
closecons();
.endif
}
.endforeach
.foreach t $(need_print_list)
.if ${index $t $(want_print_list)}
.set stat
.else
.set stat "static "
.endif
/* Print list of elements of type '$t'
* using print optimization routines.
*/
$(stat)void print_$t_list( l )
$t_list l;
{
openlist();
while( l!=$tNIL ){
print_$t( l );
l=l->next;
}
closelist();
}
.endforeach
/*********************************************************
* fprint_<type> and fprint_<type>_list routines *
*********************************************************/
.. Forward declarations
.foreach t $(need_fprint)
.if ${index $t $(want_fprint)}
.else
static void fprint_$t();
.endif
.endforeach
.foreach t $(need_fprint_list)
.if ${index $t $(want_fprint_list)}
.else
static void fprint_$t_list();
.endif
.endforeach
.foreach t $(need_fprint)
.if ${index $t $(want_fprint)}
.set stat
.else
.set stat "static "
.endif
/* Print an element of type '$t' to file 'f' */
$(stat)void fprint_$t( f, t )
FILE *f;
$t t;
{
if( t==$tNIL ){
fprintf( f, tm_niltxt );
return;
}
.if ${len ${telmlist $t}}
putc( '(', f );
.set first 1
.foreach sname ${telmlist $t}
.if $(first)
.set first 0
.else
putc( ',', f );
.endif
.if ${eq list ${ttypeclass $t $(sname)}}
fprint_${ttypename $t $(sname)}_list( f, t->$(sname) );
.else
fprint_${ttypename $t $(sname)}( f, t->$(sname) );
.endif
.endforeach
fputs( ")\n", f );
.else
putc( '(', f );
switch( t->tag ){
.foreach c ${conslist $t}
case TAG$c:
fputs( "$c", f );
.foreach sname ${celmlist $t $c}
putc( ' ', f );
.if ${eq list ${ctypeclass $t $c $(sname)}}
fprint_${ctypename $t $c $(sname)}_list( f, (($c) t)->$(sname) );
.else
fprint_${ctypename $t $c $(sname)}( f, (($c) t)->$(sname) );
.endif
.endforeach
break;
.endforeach
default:
FATALTAG( t->tag );
}
fputs( ")\n", f );
.endif
}
.endforeach
.foreach t $(need_fprint_list)
.if ${index $t $(want_fprint_list)}
.set stat
.else
.set stat "static "
.endif
/* Print list of elements of type '$t' to file 'f' */
$(stat)void fprint_$t_list( f, l )
FILE *f;
$t_list l;
{
putc( '[', f );
while( l!=$t_listNIL ){
fprint_$t( f, l );
l=l->next;
if( l!=$tNIL ){
putc( ',', f );
}
}
fputs( "]\n", f );
}
.endforeach
/*********************************************************
* rdup_<type> and rdup_<type>_list routines *
*********************************************************/
.. forward declarations
.foreach t $(need_rdup)
.if ${index $t $(want_rdup)}
.else
static $t rdup_$t();
.endif
.endforeach
.foreach t $(need_rdup_list)
.if ${index $t $(want_rdup_list)}
.else
static $t_list rdup_$t_list();
.endif
.endforeach
.foreach t $(need_rdup)
.if ${index $t $(want_rdup)}
.set stat
.else
.set stat "static "
.endif
/* Recursively duplicate instance `e' of type `$t'
* and all elements in it.
*/
$(stat)$t rdup_$t( e )
$t e;
{
.if ${len ${telmlist $t}}
.foreach e ${telmlist $t}
.if ${eq list ${ttypeclass $t $e}}
${ttypename $t $e}_list i_$e;
.else
${ttypename $t $e} i_$e;
.endif
.endforeach
if( e == $tNIL ) return $tNIL;
.foreach e ${telmlist $t}
.if ${eq list ${ttypeclass $t $e}}
i_$e = rdup_${ttypename $t $e}_list( e->$e );
.else
i_$e = rdup_${ttypename $t $e}( e->$e );
.endif
.endforeach
return new_$t( ${seplist ", " ${prefix "i_" ${telmlist $t}}} );
.else
if( e == $tNIL ) return $tNIL;
switch( e->tag ){
.foreach c ${conslist $t}
case TAG$c:
{
.foreach e ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $e}}
${ctypename $t $c $e}_list i_$e;
.else
${ctypename $t $c $e} i_$e;
.endif
.endforeach
.foreach e ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $e}}
i_$e = rdup_${ctypename $t $c $e}_list( (($c) e)->$e );
.else
i_$e = rdup_${ctypename $t $c $e}( (($c) e)->$e );
.endif
.endforeach
return new_$c( ${seplist ", " ${prefix "i_" ${celmlist $t $c}}} );
}
.endforeach
default:
FATALTAG( e->tag );
}
return $tNIL;
.endif
}
.endforeach
.foreach t $(need_rdup_list)
.if ${index $t $(want_rdup_list)}
.set stat
.else
.set stat "static "
.endif
/* recursively duplicate an instance of a `$t' list */
$(stat)$t_list rdup_$t_list( tm_e )
$t_list tm_e;
{
$t_list new;
if( tm_e == $t_listNIL ) return $t_listNIL;
new = rdup_$t( tm_e );
new->next = rdup_$t_list( tm_e->next );
return new;
}
.endforeach
/*********************************************************
* cmp_<type> and cmp_<type>_list routines *
*********************************************************/
.. Forward declarations
.foreach t $(need_cmp)
.if ${index $t $(want_cmp)}
.else
static int cmp_$t();
.endif
.endforeach
.foreach t $(need_cmp_list)
.if ${index $t $(want_cmp_list)}
.else
static int cmp_$t_list();
.endif
.endforeach
.foreach t $(need_cmp)
.if ${index $t $(want_cmp)}
.set stat
.else
.set stat "static "
.endif
.if ${len ${telmlist $t}}
.. cmp tuple
/* Compare two $t tuples. */
$(stat)int cmp_$t( a, b )
register $t a;
register $t b;
{
register int res;
res = 0;
.set first 1
.foreach ename ${telmlist $t}
.if ${eq list ${ttypeclass $t $(ename)}}
.set tn ${ttypename $t $(ename)}_list
.else
.set tn ${ttypename $t $(ename)}
.endif
.if $(first)
.set first 0
.else
if( res != 0 ) return res;
.endif
res = cmp_$(tn)( a->$(ename), b->$(ename) );
.endforeach
return res;
}
.else
.. cmp constructor
/* Compare two $t constructors */
$(stat)int cmp_$t( a, b )
$t a;
$t b;
{
register int res;
res = ((int) a->tag - (int) b->tag);
if( res != 0 ) return res;
switch( a->tag )
{
.foreach c ${conslist $t}
case TAG$c:
.set first 1
.foreach ename ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $(ename)}}
.set tn ${ctypename $t $c $(ename)}_list
.else
.set tn ${ctypename $t $c $(ename)}
.endif
.if $(first)
.set first 0
.else
if( res != 0 ) break;
.endif
res = cmp_$(tn)( (($c) a)->$(ename), (($c) b)->$(ename) );
.endforeach
break;
.endforeach
default:
FATALTAG( a->tag );
}
return res;
}
.endif
.endforeach
.foreach t $(need_cmp_list)
.if ${index $t $(want_cmp_list)}
.set stat
.else
.set stat "static "
.endif
/* Compare two $t lists. */
$(stat)int cmp_$t_list( a, b )
register $t_list a;
register $t_list b;
{
register int res;
while( (a!=$tNIL) || (b!=$tNIL) ){
if( a==$tNIL ) return -1;
if( b==$tNIL ) return 1;
res = cmp_$t( a, b );
if( res != 0 ) return res;
a = a->next;
b = b->next;
}
return 0;
}
.endforeach
/*********************************************************
* fscan_<type> and fscan_<type>_list routines *
*********************************************************/
.. Forward declarations
.foreach t $(need_fscan)
.if ${index $t $(want_fscan)}
.else
static int fscan_$t();
.endif
.endforeach
.foreach t $(need_fscan_list)
.if ${index $t $(want_fscan_list)}
.else
static int fscan_$t_list();
.endif
.endforeach
.foreach t $(need_fscan)
.if ${index $t $(want_fscan)}
.set stat
.else
.set stat "static "
.endif
.if ${len ${telmlist $t}}
/* Read a tuple of type '$t' from file 'f',
and create an instance of a C structure for it.
Set '*p' to this new structure.
*/
$(stat)int fscan_$t( f, p )
FILE *f;
$t *p;
{
.foreach ename ${telmlist $t}
.if ${eq list ${ttypeclass $t $(ename)}}
.set tn ${ttypename $t $(ename)}_list
.else
.set tn ${ttypename $t $(ename)}
.endif
$(tn) l_$(ename);
.endforeach
register short int err;
.foreach ename ${telmlist $t}
.if ${eq list ${ttypeclass $t $(ename)}}
.set tn ${ttypename $t $(ename)}_list
.else
.set tn ${ttypename $t $(ename)}
.endif
l_$(ename)=$(tn)NIL;
.endforeach
*p = $tNIL;
err = tmfneedc( f, '(' );
if(err) return(1);
.set first 1
.foreach ename ${telmlist $t}
.if $(first)
.set first 0
.else
if(!err) err = tmfneedc( f, ',' );
.endif
.if ${eq list ${ttypeclass $t $(ename)}}
.set tn ${ttypename $t $(ename)}_list
.else
.set tn ${ttypename $t $(ename)}
.endif
if(!err) err = fscan_$(tn)( f, &l_$(ename) );
.endforeach
*p = new_$t( ${seplist ", " ${prefix " l_" ${telmlist $t}}} );
if(err) return(1);
return tmfneedc( f, ')' );
}
.else
.foreach c ${conslist $t}
/* Constructor name '$c' was encountered in file 'f',
read remainder of constructor, and create an instance of
a C structure for it. set '*p' to this new structure.
*/
static int fscan_$c( f, p )
FILE *f;
$t *p;
{
.foreach ename ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $(ename)}}
.set tn ${ctypename $t $c $(ename)}_list
.else
.set tn ${ctypename $t $c $(ename)}
.endif
$(tn) l_$(ename);
.endforeach
register short int err = 0;
.foreach ename ${celmlist $t $c}
.if ${eq list ${ctypeclass $t $c $(ename)}}
.set tn ${ctypename $t $c $(ename)}_list
.else
.set tn ${ctypename $t $c $(ename)}
.endif
l_$(ename)=$(tn)NIL;
if(!err) err = fscan_$(tn)( f, &l_$(ename) );
.endforeach
*p = new_$c( ${seplist ", " ${prefix " l_" ${celmlist $t $c}}} );
return(err);
}
.endforeach
/* Read an instance of a datastructure of type $t.
from file 'f' and allocate space for it. Set the pointer 'p' to
point to that structure.
*/
$(stat)int fscan_$t( f, p )
FILE *f;
$t *p;
{
int n;
char word[WORDBUFSIZE];
register short int err = 0;
*p = $tNIL;
n = fscanopenbrac( f );
if( fscancons( f, word ) ) return 1;
.set els
.foreach c ${conslist $t}
$(els)if( strcmp( word, "$c" ) == 0 ){
err = fscan_$c( f, p );
}
.set els "else "
.endforeach
else {
(void) sprintf( tmerrmsg, tm_badcons, "$t", word );
return 1;
}
if(err) return(1);
return fscanclosebrac( f, n );
}
.endif
.endforeach
.foreach t $(need_fscan_list)
.if ${index $t $(want_fscan_list)}
.set stat
.else
.set stat "static "
.endif
/* Read an instance of a list of datastructure of type $t.
from file 'f' and allocate space for it. Set the pointer 'p' to
point to that structure.
*/
$(stat)int fscan_$t_list( f, p )
FILE *f;
$t_list *p;
{
int n;
register int c;
$t new;
register short int err = 0;
*p = $tNIL;
n = fscanopenbrac( f );
if( tmfneedc( f, '[' ) ) return 1;
if( fscanspace( f ) ) return 1;
c = getc( f );
if( c == EOF ){
(void) strcpy( tmerrmsg, tm_badeof );
return 1;
}
if( c == ']' ) return 0;
ungetc( c, f );
while( 1 ){
err = fscan_$t( f, &new );
*p = app_$t_list( *p, new );
if(err) return 1;
if( fscanspace( f ) ) return 1;
c = getc( f );
if( c == EOF ){
(void) strcpy( tmerrmsg, tm_badeof );
return 1;
}
if( c != ',' ){
ungetc( c, f );
break;
}
}
if( tmfneedc( f, ']' ) ) return 1;
return fscanclosebrac( f, n );
}
.endforeach
.if ${index stat_$(basename) $(need_misc)}
/*********************************************************
* Statistics printing routines *
*********************************************************/
.if ${index stat_$(basename) $(want_misc)}
.set stat
.else
.set stat "static "
.endif
/* give statistics */
void stat_$(basename)( f )
FILE *f;
{
#ifdef STAT
.foreach t $(need_stat)
.if ${len ${telmlist $t}}
fprintf(f,tm_allocfreed,"$t",newcnt_$t,frecnt_$t,((newcnt_$t==frecnt_$t)? "": "<-"));
.else
.foreach c ${conslist $t}
fprintf(f,tm_allocfreed,"$c",newcnt_$c,frecnt_$c,((newcnt_$c==frecnt_$c)? "": "<-"));
.endforeach
.endif
.endforeach
#else
f = f; /* to prevent 'f unused' from compiler and lint */
#endif
}
.endif
/* ---- end of ${tplfilename} ---- */